/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
package br.jm.acionista.filter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Contém métodos auxiliares que podem ser utilizados pelos backing beans das
 * páginas JSF. Para utilizar os métodos desta classe, basta fazer com que o
 * backing bean extenda esta classe.
 *
 * @author root
 */
@SuppressWarnings("unchecked")
public class PageBase {

    protected FacesContext facesContext = null;
    protected Map requestScope;
    private String RESOURCE_BUNDLE;
    protected Map<String, Object> sessionScope;
    protected Map<String, Object> applicationScope;
    protected Map<String, String> requestParam;
    private boolean hasErrors = false;

    public PageBase() {
        this.initialize();
        this.RESOURCE_BUNDLE = "messages";

    }

    /** 
    * Construtor recebe o nome do arquivo de mensagens 
    *  
    * @param resourceBundle 
    */
    public PageBase(String resourceBundle) {
        this.initialize();

        //Pega do contexto para localizar o arquivo de mensagens correto        
        this.RESOURCE_BUNDLE = resourceBundle;
    }

    protected void initialize() {

        facesContext = FacesContext.getCurrentInstance();

        if (facesContext != null) {
            requestScope =
                    (Map) facesContext.getApplication().createValueBinding("#{requestScope}").getValue(facesContext);
            sessionScope =
                    (Map) facesContext.getApplication().createValueBinding("#{sessionScope}").getValue(facesContext);
            applicationScope =
                    (Map) facesContext.getApplication().createValueBinding("#{applicationScope}").getValue(facesContext);
            requestParam =
                    (Map) facesContext.getApplication().createValueBinding("#{param}").getValue(facesContext);
        }

    }

    protected void writeBytesAsAttachedTextFile(byte[] bytes, String fileName) throws Exception {
        if (bytes == null) {
            throw new Exception("Array de bytes nulo.");
        }

        if (fileName == null) {
            throw new Exception("Nome do arquivo é nulo.");
        }

        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
        response.setContentLength(bytes.length);
        ServletOutputStream ouputStream = response.getOutputStream();
        ouputStream.write(bytes, 0, bytes.length);
        context.responseComplete();
    }

    /** 
    * Allow overriding of facesContext for unit tests 
    *  
    * @param userManager 
    */
    public void setFacesContext(FacesContext facesContext) {
        this.facesContext = facesContext;
    }

    public FacesContext getFacesContext() {
        return facesContext;
    }

    /*************************************************************************** 
     *  
     * Bundle Resources 
     *  
     **************************************************************************/
    public String getBundleName() {
        return this.RESOURCE_BUNDLE;
    }

    public ResourceBundle getBundle() {
        try {
            FacesContext context = FacesContext.getCurrentInstance();
            HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
            return ResourceBundle.getBundle(getBundleName(), request.getLocale());
        } catch (RuntimeException e) {
            return null;
        }
    }

    /** 
     * Devolve o valor correspondente a key contido no arquivo de msgs 
     * Se a key for null ou "" devolve "" 
     * @param key 
     * @return texto que corresponde a key 
     */
    public String getText(String key) {
        String message;
        if (key == null || "".equals(key)) {
            return "";
        }

        try {
            message = getBundle().getString(key);
        } catch (java.util.MissingResourceException mre) {
            return "???" + key + "???" + " in Resource: " + this.RESOURCE_BUNDLE;
        }

        return message;
    }

    /*************************************************************************** 
    *  
    *                   Mensagens de Erros e Alertas 
    *  
    **************************************************************************/
    /** 
    * Método para adicionar mensagens de erro/alerta/informação 
    * @param preComplemento: 
    *          pré complemento da msg. 
    * @param keyOfResourceBundle: 
    *            chave no arquivo de mensagens 
    * @param posComplemento: 
    *            pós complemento da msg. 
    * @param severidade: 
    *            (FacesMessage.Serverity) erro, fatal, info, alert 
    * @see {@link FacesMessage} 
    */
    protected void addMsg(String preComplemento, String keyOfResourceBundle,
            String posComplemento, FacesMessage.Severity severidade, String clientId) {

        // Acesso ao Contexto de mensagens  
        FacesContext contexto = FacesContext.getCurrentInstance();
        FacesMessage msg = new FacesMessage();
        msg.setSeverity(severidade);

        if (preComplemento == null) {
            preComplemento = "";
        }
        if (posComplemento == null) {
            posComplemento = "";
        }

        //msg.setSummary(preComplemento + this.getText(keyOfResourceBundle)  
        //      + posComplemento);  
        //msg.setDetail("*");  

        //contexto.addMessage(clientId, msg);  

        if (!(FacesMessage.SEVERITY_WARN == severidade || FacesMessage.SEVERITY_INFO == severidade)) {
            hasErrors = true;
        }

        if ("yes".equals((String) this.getBundle().getObject(
                "custom.message.put.errors.on.request"))) {

            if (FacesMessage.SEVERITY_ERROR == severidade || FacesMessage.SEVERITY_FATAL == severidade) {
                //put all error messages on requestScope  

                msg.setSummary(preComplemento + this.getText(keyOfResourceBundle)
                        + posComplemento + "~E");
                msg.setDetail("*");

                contexto.addMessage(clientId, msg);

                List reqMessages = (List) requestScope.get("custom_msg_errors");
                if (reqMessages == null) {
                    reqMessages = new ArrayList();
                }

                if (clientId == null) {
                    reqMessages.add(msg.getSummary());
                    requestScope.put("custom_msg_errors", reqMessages);
                }


            }

            if (FacesMessage.SEVERITY_INFO == severidade) {

                msg.setSummary(preComplemento + this.getText(keyOfResourceBundle)
                        + posComplemento + "~I");
                msg.setDetail("*");

                contexto.addMessage(clientId, msg);

                //put all info messages on requestScope  
                List reqMessages = (List) requestScope.get("custom_msg_success");
                if (reqMessages == null) {
                    reqMessages = new ArrayList();
                }
                reqMessages.add(msg.getSummary());
                requestScope.put("custom_msg_success", reqMessages);
            }

            if (FacesMessage.SEVERITY_WARN == severidade) {

                msg.setSummary(preComplemento + this.getText(keyOfResourceBundle)
                        + posComplemento + "~W");
                msg.setDetail("*");

                contexto.addMessage(clientId, msg);

                //put all warning messages on requestScope  
                List reqMessages = (List) requestScope.get("custom_msg_warning");
                if (reqMessages == null) {
                    reqMessages = new ArrayList();
                }
                reqMessages.add(msg.getSummary());
                requestScope.put("custom_msg_warning", reqMessages);


            }
        }
    }

    /** 
     * Método para adicionar mensagens de alerta 
     * @param preComplemento: 
     *          pré complemento da msg. 
     * @param keyOfResourceBundle: 
     *            chave no arquivo de mensagens 
     * @param posComplemento: 
     *            pós complemento da msg. 
     * @see {@link FacesMessage} 
     */
    protected void addWarningMsg(String preComplemento,
            String keyOfResourceBundle, String posComplemento) {
        this.addMsg(preComplemento, keyOfResourceBundle, posComplemento,
                FacesMessage.SEVERITY_WARN, null);
    }

    /** 
     * Método para adicionar mensagens de alerta 
     * @param keyOfResourceBundle: 
     *            chave no arquivo de mensagens 
     * @see {@link FacesMessage} 
     */
    protected void addWarningMsg(String keyOfResourceBundle) {
        this.addMsg(null, keyOfResourceBundle, null,
                FacesMessage.SEVERITY_WARN, null);
    }

    /** 
     * Método para adicionar mensagens de erro 
     * @param preComplemento: 
     *          pré complemento da msg. 
     * @param keyOfResourceBundle: 
     *            chave no arquivo de mensagens 
     * @param posComplemento: 
     *            pós complemento da msg. 
     * @param clientId: 
     *            id do component na tela ex: form:inputText1. 
     * @see {@link FacesMessage} 
     */
    protected void addErrorMsg(String preComplemento,
            String keyOfResourceBundle, String posComplemento, String clientId) {
        this.addMsg(preComplemento, keyOfResourceBundle, posComplemento,
                FacesMessage.SEVERITY_ERROR, clientId);
    }

    /** 
     * Método para adicionar mensagens de erro 
     * @param keyOfResourceBundle: 
     *            chave no arquivo de mensagens 
     * @see {@link FacesMessage} 
     */
    protected void addErrorMsg(String keyOfResourceBundle) {
        this.addMsg(null, keyOfResourceBundle, null,
                FacesMessage.SEVERITY_ERROR, null);
    }

    /** 
     * Método para adicionar mensagens de Sucesso 
     * @param preComplemento: 
     *          pré complemento da msg. 
     * @param keyOfResourceBundle: 
     *            chave no arquivo de mensagens 
     * @param posComplemento: 
     *            pós complemento da msg. 
     * @see {@link FacesMessage} 
     */
    protected void addSuccessMsg(String preComplemento,
            String keyOfResourceBundle, String posComplemento) {
        this.addMsg(preComplemento, keyOfResourceBundle, posComplemento,
                FacesMessage.SEVERITY_INFO, null);
    }

    /** 
    * Método para adicionar mensagens de sucesso 
    * @param keyOfResourceBundle: 
    *            chave no arquivo de mensagens 
    * @see {@link FacesMessage} 
    */
    protected void addSuccessMsg(String keyOfResourceBundle) {
        this.addMsg(null, keyOfResourceBundle, null,
                FacesMessage.SEVERITY_INFO, null);
    }

    public boolean isHasErrors() {
        return hasErrors;
    }

    public void setHasErrors(boolean hasErrors) {
        this.hasErrors = hasErrors;
    }
}
